A debugger is a computer-executable tool which enables a programmer to monitor the execution of a target program. Generally, a debugger can enable a program to be run step by step (called stepping) according to encoded instructions/code of a programmer, to stop at a particular line of code when a breakpoint is encountered, and can enable the value of variables to be inspected when the program is at a breakpoint or while the program is running (inspection). Some debuggers can also allow a programmer modify a target program's state data while the program is in execution (though typically stopped at a breakpoint), in addition to observing and reporting on the target program's state. Some debuggers can display and navigate the execution stack, enabling the programmer to skip over parts of code while stepping, or to restart the execution from a potentially arbitrary line of code. Other functions of debuggers include listing and debugging multiple threads at the same time, enabling hit counting, and the like.
Traditionally, though not exclusively, a debugger executes on the same computer as the target program. However, when the target code is server-side code (code operating on a remotely located computer), traditional debuggers cannot be employed. Indeed, debugging server-side code is a complex and difficult challenge. The reasons for this are many. As indicated, server-side code typically resides on a remotely-located computer, rather than on the programmer's computer where the programmer's debugger is also executing. This remoteness creates debugging issues in regard to actual examination of executing code and current program state information. Additionally, server-side code typically operates as a process that services multiple users and/or requests. Typical debugging involves setting breakpoints within the target program, i.e., points in the program where execution will be suspended while active execution will transfer to the debugger, allowing the programmer, via the debugger, to examine program execution state. However, when the target code and the debugger are executing remotely, such close interaction between the two (target program and debugger) is, at best, challenging.
Still further, with server-side code, at any one moment, any given function or module within the server-side code (i.e., a server-side target program) may be executing on multiple threads from multiple parties. Simply suspending execution of a server-side target program when a breakpoint is “hit,” which program is designed to service multiple users, will cause all users to pause—a very undesirable result. Moreover, a single breakpoint may be hit by multiple parties based on various execution conditions. Quite literally, generating breakpoint data each time a breakpoint is encountered in a server-side program operating “under load” (i.e., the simultaneous execution of the same, server-side code of multiple threads from multiple parties) generates an indecipherable, logistical quagmire of debugging data that requires substantial effort to sort out according to which set of breakpoint data belongs to which logical execution context. In short, when applying traditional debugging techniques to a server-side target program executing under load, the results require substantial time to sort out, and execution of the target program stops.
In spite of the many challenges to debugging server-side code, being able to effectively and efficiently debug server-side code, under load, is invaluable in high quality, error free, executable code that operates as a server-side service.